<?php
/* MyMeeting is an online meeting management software.
 * Copyright (C) 2009 Government Of Malaysia
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * @author: Abdullah Zainul Abidin, Nuhaa All Bakry
 *          Eavay Javay Barnad, Sarogini Muniyandi, Teow Jit Huan
 *
 */

class Committee extends AppModel {
    /**
     * Defining behavior in the model
     *
     */
    var $actsAs = array('Tree','Containable');
    /**
     * Defining the name of model
     *
     */
    var $name = 'Committee';
    /**
     * Defining the name of the table
     *
     */
    var $useTable = 'committees';
    /**
     * Displaying committee short name
     *
     */
    var $displayField = 'name';

     /**
     * Validating the fields in committee model
     *
     */
    var $validate = array(
        'name' => array(
            'required'=>array(
                'rule' => 'notEmpty'
            )
        ),
        'short_name' =>array(
            'alphaNumeric' => array('rule' => 'alphaNumeric'),
            'required'=>array(
                'rule' => 'notEmpty'
            ),
            'unique'=>array('rule' => array('checkUnique', 'short_name')),
            'nontest'=>array('rule'=>'nontest')
        ),
        'meeting_num_template' => array(
            'required'=>array(
                'rule' => 'notEmpty'
            )
        ),
        'minutetype_id' => array(
            'required'=>array(
                'rule' => 'notEmpty'
            )
        )
    );

    /**
     * Building assosiations betweeen models (ex : committee hasMany announcement)
     *
     */
    var $hasMany = array(
        'Announcement' => array(
            'className' => 'Announcement',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Item' => array(
            'className' => 'Item',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '25',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Group' => array(
            'className' => 'Group',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Meeting' => array(
            'className' => 'Meeting',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Decision' => array(
            'className' => 'Decision',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Userstatus' => array(
            'className' => 'Userstatus',
            'foreignKey' => 'decision_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Groupstatus' => array(
            'className' => 'Groupstatus',
            'foreignKey' => 'decision_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Wfmodel' => array(
            'className' => 'Wfmodel',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Todo' => array(
            'className' => 'Committeetodo',
            'foreignKey' => 'committee_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
    );

    /**
     * Building assosiations betweeen models
     *
     */
    var $hasAndBelongsToMany = array(
        'User'=> array('with'=>'Membership')
    );

    /**
     * Find all the group which the user is associated with
     * @param committee_id The committee to look in
     * @param user_id The user who's group we want to look for
     * @return an array of group id where the user is a member
     */
    function userGroups($committee_id,$user_id){
        $this->Group->recursive=-1;
        $group=Set::extract($this->Group->find('all',array('conditions'=>array(
            'committee_id'=>$committee_id,
            'Group.id'=>set::extract($this->Group->UsersGroup->find(
                'all',array('conditions'=>array('user_id'=>$user_id))
            ),'{n}.UsersGroup.group_id'),
        ))),'{n}.Group.id');
        return $group;
    }

    /**
     * Find all the decision which the user is associated with
     * @param committee_id The committee to look in
     * @param user_id The user who's status we want to look for
     * @return an array of decision id where the decision to the user
     */
    function userDecision($committee_id,$user_id){
        
        $decision=Set::extract($this->Decision->DecisionsUser->find('all',array('conditions'=>array('user_id'=>$user_id))),'{n}.DecisionsUser.decision_id');
        $groupdecision=Set::extract(
            $this->Decision->DecisionsGroup->find('list',array(
                'conditions'=> array(
                    'group_id'=>set::extract(
                        $this->Group->UsersGroup->find('all',array('conditions'=>array('user_id'=>$user_id))),
                        '{n}.UsersGroup.group_id')
                    ),
                'fields'=>array('DecisionsGroup.decision_id')
                )
            ),
        '{n}.DecisionsGroup.decision_id');
        $decision_id=array_merge($decision,$groupdecision);
        return $this->Decision->find('list',array('conditions'=>array('Decision.committee_id'=>$committee_id,'Decision.id'=>$decision_id)));
    }

    /**
     * Find all the decision which the user has updated
     * @param committee_id The committee to look in
     * @param user_id The user who's status we want to look for
     * @return an array of decision id where the decision has been updated by the user
     */
    /* 
    function updatedDecision($committee_id,$user_id){
        $this->Userstatus->Behaviors->detach('Comment');
        $this->Userstatus->Behaviors->detach('MultiFile');
        $this->Groupstatus->Behaviors->detach('Comment');
        $this->Groupstatus->Behaviors->detach('MultiFile');
        $userstatus=Set::extract(
            $this->Userstatus->find('all',array(
                'conditions'=>array(
                    'Userstatus.committee_id'=>$committee_id,
                    'Userstatus.user_id'=>$user_id
                )
            )),'{n}.Decision.id'
        );
        $groupstatus=Set::extract(
            $this->Groupstatus->find('all',array(
                'conditions'=>array(
                    'Groupstatus.committee_id'=>$committee_id,
                    'Groupstatus.group_id'=>$this->userGroups($committee_id,$user_id)
                )
            )),'{n}.Decision.id'
        );
        return array_merge($userstatus,$groupstatus);
    }
    */

    /**
     * Find all the decision which the user need to update
     * @param committee_id The committee to look in
     * @param user_id The user who's status we want to look for
     * @return an array of decision id where the decision has not been updated by the user
     */
   /* function notUpdatedDecision($committee_id,$user_id,$decision_id){
        $updated=$this->updatedDecision($committee_id,$user_id);
        $needupdating=$this->Decision->find('all',array(
            'conditions'=>array(
                'Decision.committee_id'=>$committee_id,
                'Decision.id'=>$decision_id,
                'not'=>array('Decision.id'=>$updated),
                'or'=>array(
                    'Decision.status_deadline>=now()',
                    'and'=>array(
                        'Decision.status_deadline'=>'0000-00-00',
                        'or'=>array(
                            'Decision.deadline>=now()',
                            'Decision.deadline'=>'0000-00-00'
                        )
                    )
                )
            ),
            'contain'=>array(
                    'Item.name',
                    'Item.id',
                    'Meeting.meeting_num',
                    'Meeting.id',
                    'User.name',
                    'Group.name',
            ),
            'order'=> 'deadline DESC'
        ));
        return $needupdating;
    }
    */
    
    /**
     * Find all the decision which the user need to update
     * @param committee_id The committee to look in
     * @param user_id The user who's status we want to look for
     * @param $decision_id which user are its implementor  
     * @return an array of decision id which the user need to update
     */
    function needupdating($committee_id,$user_id,$decision_id){
        $decisions=$this->Decision->find('all',array(
            'conditions'=>array(
                'Decision.committee_id'=>$committee_id,
                'Decision.id'=>$decision_id,
                /*
                 * 'or'=>array(
                    'Decision.status_deadline>=now()',
                    'and'=>array(
                        'Decision.status_deadline'=>'0000-00-00',
                        'or'=>array(
                            'Decision.deadline>=now()',
                            'Decision.deadline'=>'0000-00-00'
                        )
                    )
                )
                * */
            ),
            'contain'=>array(
                    'User.id',
                    'Group.id',
                    'Groupstatus.group_id',
                    'Userstatus.user_id'
            ),
            'fields'=>array('Decision.id')
        ));
        $needupdatings_id=array();
        $group_id=$this->userGroups($committee_id,$user_id);
        foreach($decisions as $decision){
            $needupdating=$this->Decision->needupdating($decision,1);
            if (in_array($user_id,Set::extract('/User/id',$needupdating)) ||(array_intersect($group_id,set::extract('/Group/id',$needupdating)))){
                $needupdatings_id[]=$decision['Decision']['id'];
            }
        }
        $needupdatings=$this->Decision->find('all',array(
            'conditions'=>array(
                'Decision.committee_id'=>$committee_id,
                'Decision.id'=>$needupdatings_id,
                /*
                'or'=>array(
                    'Decision.status_deadline>=now()',
                    'and'=>array(
                        'Decision.status_deadline'=>'0000-00-00',
                        'or'=>array(
                            'Decision.deadline>=now()',
                            'Decision.deadline'=>'0000-00-00'
                        )
                    )
                )
                * */
            ),
            'contain'=>array(
                    'Item.name',
                    'Item.id',
                    'Meeting.meeting_num',
                    'Meeting.id',
                    'User.name',
                    'Group.name'
            ),
            'fields'=>array(
                'Decision.id',
                'Decision.description',
                'Decision.deadline',
                'Decision.status_deadline'
            )
        ));
        return $needupdatings;
    }

    /**
     * Finding all the related userdata defined by the committee_id and user_id
     * $param committee_id and user_id finds all the related userdata
     */
    function userData($user_id,$committee_id=null){
        $groups=$this->Membership->User->UsersGroup->find('all',array(
        'fields'=>array('group_id'),
            'conditions'=>array('user_id'=>$user_id),
        ));
        $toret['groups']=Set::extract($groups,"{n}.UsersGroup.group_id");
        $role=$this->Membership->find('first',array(
            'fields'=>array('role_id'),
            'conditions'=>array('user_id'=>$user_id,'committee_id'=>$committee_id),
            'contain'=>array('Role.name')
        ));
        $toret['role']=$role['Role']['name'];
        return $toret;
    }

    /**
     * Finding all the related committees per user defined by the user_id order by committee name
     * $param user_id finds all the committees per user
     */
    function getCommitteesPerUser($user_id) {
        $committees = $this->Membership->findAll(
            array(
                'conditions'=>array(
                    'Membership.user_id'=>$user_id)
                ),
                'Committee.*',
                'Committee.name ASC');
        return $committees;
    }

    /**
     * Finding all the related registered committee defined by the user_id order by committee name
     * $param user_id finds all the registered committee
     */
    function registeredCommittee($user_id){
        return Set::extract($this->Membership->find('all',array('fields'=>'committee_id','conditions'=>array('user_id'=>$user_id))),"{n}.Membership.committee_id");
    }

    /**
     * Finding all the related list of registered committee defined by the user_id order by committee name
     * $param user_id finds all the list of registered committee
     */
    function registeredCommitteeList($user_id){
        return $this->find('all',array('contain'=>false,'fields'=>array('id','short_name','name','parent_id'),'order'=>'name ASC, parent_id ASC','conditions'=>array('id'=>$this->registeredCommittee($user_id))));
    }

    /**
     * Allowing afterSave() callbacks to modify the value of a data field.
     * @param created modifies the value of a data field.
     */
    function afterSave($created){
        if($created){
            $comid=$this->getLastInsertID();
            
            // committee members can see this, only admin can edit
            $this->Wfmodel->create();
            $data['view']=$wfdata['view']='all';
            $data['edit']=$wfdata['edit']='role:admin';
            $data['delete']=$wfdata['delete']='role:admin';
            $data['committee_id']=$comid;
            $data['create']='role:admin';
            $data['model']='Meeting'; 
            $this->Wfmodel->save($data);


            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Decision';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Item';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Membership';
            $this->Wfmodel->save($data);
            
            // only admin can see this
            $data['view']=$wfdata['view']='role:admin';

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Committee';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Wfmodel';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Committeetodo';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Group';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Announcement';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Template';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Attendance';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Meetingtodo';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Protocol';
            $this->Wfmodel->save($data);
            
            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Minutetype';
            $this->Wfmodel->save($data);
            
            // only admin and owner can edit this
            $data['create']='role:admin,owner';
            $data['view']=$wfdata['all']='role:admin';

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Userstatus';
            $this->Wfmodel->save($data);

            $this->Wfmodel->create();
            $wfdata['model']=$data['model']='Groupstatus';
            $this->Wfmodel->save($data);

        }
    }


   /* 
    function getSearchResults($dcommittee,$status) {

        // query for latest status for each user
        $finder = 'SELECT Status.*, User.*
            FROM `userstatuses` AS `Status`
            JOIN `users` AS `User` ON (`Status`.`user_id` = `User`.`id`)
            LEFT JOIN userstatuses as s2 ON (Status.user_id=s2.user_id and Status.decision_id=s2.decision_id and Status.updated < s2.updated)
            WHERE s2.id is NULL AND Status.action_date != "0000-00-00" AND Status.decision_id IN ({$__cakeID__$}) ';

        // then bind it to each decision
        $this->Meeting->Decision->bindModel(array('hasMany'=>array(
            'Status' => array(
                'className' => 'Userstatus',
                'foreignKey' => 'decision_id',
                'dependent' => false,
                'conditions' => '',
                'fields' => '',
                'order' => '',
                'limit' => '',
                'offset' => '',
                'exclusive' => '',
                'finderQuery' => $finder,
                'counterQuery' => ''))));

        // get all decisions for this committee
        $result=$this->Meeting->Decision->findAll(array('Meeting.committee_id'=>$dcommittee['Committee']['id']),
            '',
            'Meeting.meeting_title,Item.name,Decision.deadline ASC');

        // determine condition based on search criteria
        switch ($status) {
        case 'takenontime' : $cond = 'Userstatus.action_date <= Decision.deadline';
            break;
        case 'takenlate' : $cond = 'Userstatus.action_date > Decision.deadline';
            break;
        }

        // get all status fulfilling the search criteria
        $filter=$this->Meeting->Decision->Userstatus->findAll($cond,array('Userstatus.*'));

        // get decision ids from it
        $decision_ids = array();
        foreach ($filter as $f) {
            array_push($decision_ids,$f['Userstatus']['decision_id']);
        }
        $decision_ids = array_unique($decision_ids);

        // then filter it to get decisions to display based on search criteria
        foreach ($result as $key=>$value) {
            if (!in_array($value['Decision']['id'],$decision_ids))
                unset($result[$key]);
        }
        //echo "<pre>".print_r($decision_ids,true)."</pre>";

        return $result;
    }
    */

    /**
     * Finding all the decision status which is not taken and on time defined by the committee_id
     * $param committee_id finds all the decision status which is not taken for the specified user type
     * $param date = selected date range
     */
    function nottaken($committee_id,$type='User',$date=null){
        $cond=$type.'Status.id is null and Decision.deadline>=now() and Meeting.deleted=0 and Meeting.committee_id='.$committee_id;
        if (!empty($date)){
            $cond.=' and '.$date;
        }
        return $this->query($this->statusquery($type,$cond,false));
    }

    /**
     * Finding all the decision status which is not taken and over due defined by the committee_id
     * $param committee_id finds all the decision status which is not taken for the specified user type
     * $param date = selected date range
     */
    function nottakenlate($committee_id,$type='User',$date=null){
        $cond=$type.'Status.id is null and Decision.deadline<now() and Meeting.deleted=0 and Meeting.committee_id='.$committee_id;
        if (!empty($date)){
            $cond.=' and '.$date;
        }
        return $this->query($this->statusquery($type,$cond,false));
    }

    /**
     * Finding all the decision status which is taken and on time defined by the committee_id
     * $param committee_id finds all the decision status which is taken and on time for the specified user type
     * $param date = selected date range
     */
    function takenontime($committee_id,$type='User',$date=null){
        $cond=$type.'Status.action_date<=Decision.deadline and Meeting.deleted=0 and Meeting.committee_id='.$committee_id;
        if (!empty($date)){
            $cond.=' and '.$date;
        }
        return $this->query($this->statusquery($type,$cond));
    }

    /**
     * Finding all the decision status which is taken and late defined by the committee_id
     * $param committee_id finds all the decision status which is taken and late for the specified user type
     * $param date = selected date range
     */
    function takenlate($committee_id,$type='User',$date=null){
        $cond=$type.'Status.action_date>Decision.deadline and Meeting.deleted=0 and Meeting.committee_id='.$committee_id;
        if (!empty($date)){
            $cond.=' and '.$date;
        }
        return $this->query($this->statusquery($type,$cond));
    }

     /**
     * Finding all the decision status which in date range
     * $param committee_id finds all the decision status for the specified user type
     * $param date = selected date range
     */
    function statusInDate($committee_id,$type='User',$date=null){
        if($date){
            $cond=$date.' and Meeting.deleted=0 and Meeting.committee_id='.$committee_id;
        }else{
            $cond=' Meeting.deleted=0 and Meeting.committee_id='.$committee_id;
        }
        return $this->query($this->statusquery($type,$cond,false));
    }

    /**
     * Query all the decision status for the specified user type
     */
    function statusquery($type='User',$cond,$taken=true){
        $statusjoin='';
        if(!$taken){
            $statusjoin='left';
        }
        $fields = 'Meeting.meeting_title, Meeting.meeting_num, Item.name, Decision.description, Decision.deadline, Decision.id, '.$type.'.name, '.$type.'Status.description, '.$type.'Status.action_date';
        
        $sql = 'select '.$fields.' from decisions_'.low($type).'s as Decision'.$type.' ';
        $sql.= $statusjoin.' join '.low($type).'statuses as '.$type.'Status ';
        $sql.= ' on ('.$type.'Status.decision_id=Decision'.$type.'.decision_id and '.$type.'Status.'.low($type).'_id=Decision'.$type.'.'.low($type).'_id)';
        $sql.= ' left join '.low($type).'statuses as s2 ';
        $sql.= ' on ('.$type.'Status.decision_id=s2.decision_id and '.$type.'Status.'.low($type).'_id=s2.'.low($type).'_id and '.$type.'Status.updated < s2.updated ) ';
        $sql.= ' join '.low($type).'s as `'.$type.'`';
        $sql.= ' on ('.$type.'.id=Decision'.$type.'.'.low($type).'_id) ';
        $sql.= ' join decisions as Decision on (Decision'.$type.'.decision_id=Decision.id) ';
        $sql.= ' left join items as Item on (Decision.item_id=Item.id) ';
        $sql.= ' left join meetings as Meeting on (Decision.meeting_id=Meeting.id) ';
        $sql.= ' where s2.id is null and '.$cond;
        return $sql;
    }

    /**
     * Describe getCommittees
     * Funtion to find all subcommittees under parent $parent registered for $user_id
     * @param $parent
     * @param $user_id
     * @return array
     */
    function getCommittees($user_id,$get_permission=false){
        // get tree structure
        $this->recursive=-1;
        $mycommittees = $this->generatetreelist(array('id'=>$this->registeredCommittee($user_id)), null, '{n}.Committee.name', '_');
        if ($get_permission) {
            $onlythiscommittees = array_keys($mycommittees);
            // get committees details
            $committees = $this->find('all', array('conditions'=>array('id'=>$onlythiscommittees)));
            // append it
            foreach ($mycommittees as $key=>$com){
                foreach ($committees as $keyc=>$value) {
                    if ($value['Committee']['id'] == $key) {
                        $mycommittees[$key.'_details'] = array();
                        array_push($mycommittees[$key.'_details'], $value['Committee']);
                        unset($committees[$keyc]);
                        break;
                    }
                }
            }
        }
        return $mycommittees;
    }

/**
     * Describe getCommitteesId
     * Funtion to find all registered committee id for $user_id
     * @param $user_id
     * @return array
     */
    function getCommitteesId($user_id){
        $mycommittees = $this->registeredCommittee($user_id);
        return set::extract($this->find('all',array('conditions'=>array('Committee.id'=>$mycommittees))),'{n}.Committee.id');
    }

     /**
     * Describe getAuto
     * Funtion to find all related data with keyword
     * @param $dtext
     * @param $user_id
     * @return $text (array)
     * - $text[$i][1]=>link and $text[$i][0]=>data
     */
    function getAuto($dtext,$user_id){
        //use getMulti function because same query
        $t=$this->getMulti($dtext,$user_id);
        $i=0;
        if ($t) {
            if(!empty($t[1])){
                for($j=1;(!empty($t[1][$j]));++$j){
                    $text[$i][1]=$t[1][$j][1];
                    $text[$i][0]=$t[1][$j][0]['Decision']['description'];
                    ++$i;
                }
            }
            if(!empty($t[2])){
                for($j=1;(!empty($t[2][$j]));$j++){
                    $text[$i][1]=$t[2][$j][1];
                    $text[$i][0]=$t[2][$j][0]['Attachment']['filename'];
                    ++$i;
                }
            }
            if(!empty($t[3])){
                for($j=1;(!empty($t[3][$j]));$j++){
                    $text[$i][1]=$t[3][$j][1];
                    $text[$i][0]=$t[3][$j][0]['Meeting']['meeting_title'].', '.$t[3][$j][0]['Meeting']['meeting_num'];
                    ++$i;
                }
            }
            if(!empty($t[4])){
                for($j=1;(!empty($t[4][$j]));$j++){
                    $text[$i][1]=$t[4][$j][1];
                    $text[$i][0]=$t[4][$j][0]['Item']['name'];
                    ++$i;
                }
            }
            if(!empty($t[5])){
                for($j=1;(!empty($t[5][$j]));$j++){
                    $text[$i][1]=$t[5][$j][1];
                    $text[$i][0]=$t[5][$j][0]['Groupstatus']['description'];
                    ++$i;
                }
            }
            if(!empty($t[6])){
                for($j=1;(!empty($t[6][$j]));$j++){
                    $text[$i][1]=$t[6][$j][1];
                    $text[$i][0]=$t[6][$j][0]['Userstatus']['description'];
                    ++$i;
                }
            }
            $a=set::extract($text,'{n}.0');
            natcasesort($a);
            $text['sort']=array_keys($a);
            return $text;
        } else {
            return '';
        }
    }
     /**
     * Describe getMulti
     * Funtion to find all related data with keyword
     * @param $dtext
     * @param $user_id
     * @return $text (array)
     * - $text[$j][$i][1]=>link and $text[$j][$i][0]=>the related data
     * --$j==type (decision,attachment,meeting,item,status);$i==number in certain type;
     */
     function getMulti($dtext=null,$user_id){
        $this->unbindModel(array('hasMany'=>array('Announcement','Item','Group','Meeting','Decision','Todo','Userstatus','Groupstatus','Wfmodel'),'hasAndBelongsToMany'=>array('User','Membership')),false);
        $this->Meeting->Behaviors->detach('Comment');
        $this->Meeting->Behaviors->detach('MultiFile');
        $this->Meeting->unbindModel(array('hasMany'=>array('Decision','Todo','Notification'),'hasAndBelongsToMany'=>array('User','Membership')),false);
        $this->Item->unbindModel(array('hasMany'=>array('Decision')),false);
        $this->Groupstatus->recursive=-1;
        $this->Groupstatus->Behaviors->detach('Comment');
        $this->Groupstatus->Behaviors->detach('MultiFile');
        $this->Userstatus->recursive=-1;
        $this->Userstatus->Behaviors->detach('Comment');
        $this->Userstatus->Behaviors->detach('MultiFile');
        if($dtext[0]!=''){
            $committees=$this->registeredCommitteeList($user_id);
            $comm=array();
            foreach($committees as $c){
                $comm[]=$c['Committee']['id'];
                $comm_name[$c['Committee']['id']]=$c['Committee']['short_name'];
            }
            $text=array();
            $deleted=$this->deletedDecisionId();
            $this->Decision->Behaviors->detach('Comment');
            $this->Decision->Behaviors->detach('MultiFile');
            $this->Decision->unbindModel(array('hasMany'=>array('Userstatus','Groupstatus'),'hasAndBelongsToMany'=>array('User','Group')),false);
            
            // Decisions
            $decisions=$this->Decision->find('all',array('fields'=>array('id','description','committee_id','deadline'),'contain'=>false,'conditions'=>array('Decision.description LIKE'=>'%'.$dtext[2].'%','Decision.committee_id'=>$comm,'not'=>array('Decision.id'=>$deleted))));
            $i=0;
            foreach($decisions as $decision){
                $decision['Decision']['description']=$this->processDecisionDescp($decision['Decision']['description']);
                if(stripos(' '.$decision['Decision']['description'],$dtext[0])!==false){
                    $i++;
                    $text[1][$i][1]=array('controller'=>'decisions','action'=>'view','committee'=>$comm_name[$decision['Decision']['committee_id']],$decision['Decision']['id']);
                    $text[1][$i][0]=$decision;
                }
            }
            
            // Attachments
            $this->Attachment=ClassRegistry::init('Attachment','model');
            $attachments=$this->Attachment->CommitteeFile($comm,$deleted,array('Attachment.filename LIKE'=>'%'.$dtext[1].'%'));
            $i=0;
            foreach($attachments as $attachment){
                $i++;
                if($attachment['Attachment']['model']=='Meeting'){
                    $text[2][$i][1]=array('committee'=>$comm_name[$attachment['Meeting']['committee_id']],'controller'=>'meetings','action'=>'attachment','id'=>$attachment['Attachment']['id']);
                    $text[2][$i][0]=$attachment;
                }
                elseif($attachment['Attachment']['model']=='Decision'){
                    $text[2][$i][1]=array('committee'=>$comm_name[$attachment['Decision']['committee_id']],'controller'=>'decisions','action'=>'attachment','id'=>$attachment['Attachment']['id']);
                    $text[2][$i][0]=$attachment;
                }
                elseif($attachment['Attachment']['model']=='Groupstatus'){
                    $text[2][$i][1]=array('committee'=>$comm_name[$attachment['Groupstatus']['committee_id']],'controller'=>'groupstatuses','action'=>'attachment','id'=>$attachment['Attachment']['id']);
                    $text[2][$i][0]=$attachment;
                }
                elseif($attachment['Attachment']['model']=='Userstatus'){
                    $text[2][$i][1]=array('committee'=>$comm_name[$attachment['Userstatus']['committee_id']],'controller'=>'userstatuses','action'=>'attachment','id'=>$attachment['Attachment']['id']);
                    $text[2][$i][0]=$attachment;
                }
            }
            //meeting
            if(strpos(' '.$dtext[0],',')){
                $txt=explode(', ',$dtext[0]);
                $txt=$txt[1];
            }else{
                $txt=$dtext[0];
            }
            $meetings=$this->Meeting->find('all',array('fields'=>array('meeting_title','meeting_num','committee_id','id','meeting_date','venue'),'contain'=>false,'conditions'=>array('Meeting.committee_id'=>$comm,'or'=>array('Meeting.meeting_num LIKE'=>'%'.$txt.'%','Meeting.meeting_title LIKE'=>'%'.$txt.'%'))));
            $i=0;
            foreach($meetings as $meeting){
                if(stripos(' '.$meeting['Meeting']['meeting_title'].', '.$meeting['Meeting']['meeting_num'],$dtext[0])!==false){
                    $i++;
                    $text[3][$i][1]=array('committee'=>$comm_name[$meeting['Meeting']['committee_id']],'controller'=>'meetings','action'=>'view','id'=>$meeting['Meeting']['id']);
                    $text[3][$i][0]=$meeting;
                }
            }
            
            // Item
            $this->Item->recursive = -1;
            $items=$this->Item->find('all',array('fields'=>array('`Item`.`id`', '`Item`.`committee_id`', '`Item`.`name`', '`Item`.`description`'), 'conditions'=>array('Item.name LIKE'=>'%'.$dtext[1].'%','Item.committee_id'=>$comm)));
            $i=0;
            foreach($items as $item){
                $i++;
                $text[4][$i][1]=array('committee'=>$comm_name[$item['Item']['committee_id']],'controller'=>'items','action'=>'view',$item['Item']['id']);
                $text[4][$i][0]=$item;
            }
            
            // group status
            $gdata=$this->Groupstatus->find('all',array('fields'=>array('group_id','decision_id'),'conditions'=>array('Groupstatus.description LIKE'=>'%'.$dtext[1].'%','Groupstatus.committee_id'=>$comm,'not'=>array('Groupstatus.decision_id'=>$deleted))));
            $gdata=$this->unique(set::extract($gdata,'{n}.Groupstatus'));
            $i=0;
            if(!empty($gdata)){
                foreach($gdata as $data){
                    $gdecision=$this->Decision->DecisionsGroup->find('first',array('conditions'=>array('DecisionsGroup.decision_id'=>$data['decision_id'],'DecisionsGroup.group_id'=>$data['group_id'])));
                    if(!empty($gdecision)){
                        $groupstatus=$this->Groupstatus->find('first',array('fields'=>array('id','group_id','description','action_date','committee_id','decision_id'),'conditions'=>array('Groupstatus.committee_id'=>$comm,'Groupstatus.decision_id'=>$gdecision['DecisionsGroup']['decision_id'],'Groupstatus.group_id'=>$gdecision['DecisionsGroup']['group_id'],'not'=>array('Groupstatus.decision_id'=>$deleted)),'order'=>'Groupstatus.updated desc'));
                        if(stripos(' '.$groupstatus['Groupstatus']['description'],$dtext[0])){
                            $i++;
                            $text[5][$i][1]=array('controller'=>'decisions','action'=>'view','committee'=>$comm_name[$groupstatus['Groupstatus']['committee_id']],$groupstatus['Groupstatus']['decision_id']."#group".$groupstatus['Groupstatus']['id']);
                            $text[5][$i][0]=$groupstatus;
                        }
                    }
                }
            }
            
            // user status
            $udata=$this->Userstatus->find('all',array('fields'=>array('user_id','decision_id'),'conditions'=>array('Userstatus.description LIKE'=>'%'.$dtext[1].'%','Userstatus.committee_id'=>$comm,'not'=>array('Userstatus.decision_id'=>$deleted))));
            $udata=$this->unique(set::extract($udata,'{n}.Userstatus'));
            $i=0;
            foreach($udata as $data){
                $udecision=$this->Decision->DecisionsUser->find('first',array('conditions'=>array('DecisionsUser.decision_id'=>$data['decision_id'],'DecisionsUser.user_id'=>$data['user_id'])));
                if(!empty($udecision)){
                    $userstatus=$this->Userstatus->find('first',array('fields'=>array('id','user_id','description','action_date','committee_id','decision_id'),'conditions'=>array('Userstatus.committee_id'=>$comm,'Userstatus.decision_id'=>$udecision['DecisionsUser']['decision_id'],'Userstatus.user_id'=>$udecision['DecisionsUser']['user_id'],'not'=>array('Userstatus.decision_id'=>$deleted)),'order'=>'Userstatus.updated desc'));
                    if(stripos(' '.$userstatus['Userstatus']['description'],$dtext[0])){
                        $i++;
                        $text[6][$i][1]=array('controller'=>'decisions','action'=>'view','committee'=>$comm_name[$userstatus['Userstatus']['committee_id']],$userstatus['Userstatus']['decision_id']."#user".$userstatus['Userstatus']['id']);
                        $text[6][$i][0]=$userstatus;
                    }
                }
            }
            return $text;
        }
    }
    
     /**
     * Describe IdToShortName
     * Funtion to find shortname from the committee_id
     * @param $id
     * @return $shortname
     */
     function IdToShortName($id){
         $this->unbindModel(array('hasMany'=>array('Announcement','Item','Group','Meeting','Decision','Todo','Userstatus','Groupstatus','Wfmodel'),'hasAndBelongsToMany'=>array('User','Membership')),false);
         $dname=$this->find('first',array('field'=>('short_name'),'conditions'=>array('Committee.id'=>$id)));
         return $dname['Committee']['short_name'];
     }

     /**
     * Describe NameToId
     * Funtion to find committee_id from committee name
     * @param $name
     * @return $committee_id
     */
     function NameToId($name){
         $this->unbindModel(array('hasMany'=>array('Announcement','Item','Group','Meeting','Decision','Todo','Userstatus','Groupstatus','Wfmodel'),'hasAndBelongsToMany'=>array('User','Membership')),false);
         $did=$this->find('first',array('field'=>('id'),'conditions'=>array('Committee.name'=>$name)));
         return $did['Committee']['id'];
     }
     /**
     * Describe deletedDecisionId
     * Funtion to find all deleted decision id, included decision below deleted meeting
     * @param null
     * @return $deleted decision id
     */
    function deletedDecisionId(){
        $this->Decision->recursive=-1;
        $this->Decision->Behaviors->detach('Comment');
        $del_decision_id=array();
        $del_decision_id=set::extract($this->Decision->find('all',array('fields'=>('id'),'conditions'=>array('deleted'=>1))),'{n}.Decision.id');
        
        //find deleted meeting id
        $this->Meeting->recursive=-1;
        $del_meeting_id=set::extract($this->Meeting->find('all',array('fields'=>('id'),'conditions'=>array('Meeting.deleted'=>1))),'{n}.Meeting.id');
        $this->Meeting->recursive=1;

        if(!empty($del_meeting_id)){
            $del_decision_id1=set::extract($this->Decision->find('all',array('fields'=>('id'),'conditions'=>array('Decision.meeting_id'=>$del_meeting_id))),'{n}.Decision.id');
            if(isset($del_decision_id1)){
                $del_decision_id=array_merge($del_decision_id,$del_decision_id1);    
            }
        }
        $this->Decision->recursive=1;
        $this->Decision->Behaviors->attach('Comment');
        return $del_decision_id;
     }
     
     /**
     * Describe processSysmbol
     * Funtion to process text with sysmbol
     * @param $text
     * @return $text
     */
    function processSysmbol($text){
        $dtext[0]=$text;
        //make the sysmbol searchable
        $text=str_replace('\\','\\\\',$text);
        $sym=array('%','&','_','+',':','?','/','.','^','$','(',')','|','*','[',']');
        $sym_replace=array('\\%','\\&','\\_','\\+','\\:','\\?','\\/','\\.','\\^','\\$','\\(','\\)','\\|','\\*','\\[','\\]');
        $dtext[1]=str_replace($sym,$sym_replace,$text);
        //make the symbol searhable in decision description
        $sym_dec=array('<','>');
        $sym_dec_replace=array('&lt;','&gt;');
        $dtext[2]=str_replace($sym_dec,$sym_dec_replace,str_replace('&','&amp;',$dtext[1]));
        $dtext[3]=str_replace($sym_dec,$sym_dec_replace,str_replace('&','&amp;',$dtext[0]));
        
        return $dtext;
     }
     
     /**
     * Describe unique
     * make multidimensional array unique eg:array(array(1,2),array(1,2),array(1,3))==>array(,array(1,2),array(1,3))
     * @param $data
     * @return $result
     */
     function unique($data){
        $serial=array();
        $result=array();
        foreach($data as $d){
            $serial[]=serialize($d);
        }
        $s=array_unique($serial);
        foreach ($s as $s){
            $result[]=unserialize($s);
        } 
        return $result;
     }
     
     /*
     * For validation
     */
    function nontest($value) {
        if($value['short_name']=='test') return false;
        else return true;
    }
    
    /**
     * Describe processDecisionDescp
     * Funtion to process text with sysmbol
     * @param $text
     * @return $text
     */
    function processDecisionDescp($text){
        $text=str_replace(
            array('&lt;',"&gt;",'&amp;',"&middot;",'&nbsp;',"&ldquo;",'&rdquo;',"&bull;",'&ndash;',"&lsquo;",'&rsquo;'), 
            array('<',">",'&',"",'',"",'',"",'',"",''), 
            $text
        );
        $text=strip_tags($text);
        return $text;
        
    }
    
}
?>
